import logging
import os
import json
import time
import requests

# 全局变量设置，按需修改

hw_cloud_user = "Ascend-CANN"
hw_cloud_iam_user = "Ascend-CANN"

# 环境变量获取
hw_cloud_iam_password = os.getenv("iamPassword")  # 敏感信息
repo_access_token = os.getenv("repoAccessToken")  # 敏感信息
project_id = os.getenv("PROJECT_ID")
pipeline_id = os.getenv("pipelineID")
pipeline_run_id = os.getenv("pipelineRunID")
build_number = os.getenv("BUILDNUMBER")
repo_path = os.getenv("repoPath")
pr_id = os.getenv("prID")

# 动态设置
token = ""
common_header = {}

# comment表格
comment_header = """
<table style="border-collapse: collapse">
    <tr>
        <th>任务名称</th>
        <th>状态</th>
        <th>日志详情</th>
        <th>产物下载</td>
    </tr>
"""
comment_body = ""
comment_tail = "</table>"

# job与文件存储路径映射
job_path_dict = {
    "UT测试": "cov_report.tar",
    "Compile-X86": "CANN-custom_ops-linux.x86_64.run",
    "Compile-ARM": "CANN-custom_ops-linux.aarch64.run"
}

logging.basicConfig(level=logging.INFO, format="%(asctime)s  %(levelname)s:%(message)s")


def get_pipeline_status():
    url_get_status = f"https://cloudpipeline-ext.cn-north-4.myhuaweicloud.com/v5/{project_id}/api/pipelines/{pipeline_id}/pipeline-runs/detail?pipeline_run_id={pipeline_run_id}"
    res = requests.get(url=url_get_status, headers=common_header, verify=False)
    return json.loads(res.text)


def get_token():
    url_get_token = "https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens"
    headers_get_token = {
        "auth": {
            "identity": {
                "password": {
                    "user": {
                        "password": f"{hw_cloud_iam_password}",
                        "domain": {
                            "name": f"{hw_cloud_user}"
                        },
                        "name": f"{hw_cloud_iam_user}"
                    }
                },
                "methods": [
                    "password"
                ]
            },
            "scope": {
                "project": {
                    "name": "cn-north-4"
                }
            }
        }
    }
    res = requests.post(url=url_get_token, data=json.dumps(headers_get_token))
    logging.info(f"获取token请求状态：{res.status_code}")
    global token
    token = res.headers["X-Subject-Token"]


def download_job_log(job):
    logging.info(f"  > 启动job[{job['name']}]日志下载...")
    res, store_path = download_check_job_log(job) if job['steps'][0]['task'] == 'official_devcloud_codeCheck' \
        else download_build_job_log(job)
    os.makedirs(os.path.dirname(store_path), exist_ok=True)
    with open(store_path, "w", encoding="UTF-8") as f:
        f.write(res)
        f.close()
    logging.info(f"    > 日志[{store_path}]下载完成")
    return store_path


def download_build_job_log(job):
    logging.info(f"  > 启动job[{job['name']}]日志下载...")
    store_path = os.path.join("pipeline-logs", f"{job['name']}.txt")
    # 下边的操作针对性教强，适配其他流水线时需要重新审视，包括：
    # 1. 当前适配的流水线，每一个job只有1个step
    # 2. 当前需要追踪的日志都是构建任务中的日志，获取构建任务id的方式为查询inputs中key为"jobId"的value值
    job_id = ""
    for step_input in job["steps"][0]["inputs"]:
        if step_input["key"] == "jobId":
            job_id = step_input["value"]
            break

    daily_build_number = job["steps"][0]["daily_build_number"]
    current_build_number = ""
    url_get_build_number = f"https://cloudbuild-ext.cn-north-4.myhuaweicloud.com/v3/jobs/{job_id}/history?offset=0&limit=100&interval=30"
    res = requests.get(url=url_get_build_number, headers=common_header, verify=False)
    for record in json.loads(res.text)["history_records"]:
        if record["record_id"] == daily_build_number:
            current_build_number = record["build_number"]
            break
    logging.info(f"    > 获取build_number：{current_build_number}")

    url_get_build_info = f"https://cloudbuild-ext.cn-north-4.myhuaweicloud.com/v4/jobs/{job_id}/{current_build_number}/record-info"
    res = requests.get(url=url_get_build_info, headers=common_header, verify=False)
    record_id = json.loads(res.text)["result"]["build_record_id"]
    logging.info(f"    > 获取record_id：{record_id}")

    url_download_build_log = f"https://cloudbuild-ext.cn-north-4.myhuaweicloud.com/v4/{record_id}/download-log"
    url_download_log = url_download_build_log
    res = requests.get(url=url_download_log, headers=common_header, verify=False)
    return res.text, store_path


def download_check_job_log(job):
    store_path = os.path.join("pipeline-logs", f"{job['name']}.json")
    job_id = ""
    for step_input in job["steps"][0]["inputs"]:
        if step_input["key"] == "jobId":
            job_id = step_input["value"]
            break
    b_download_finished = False
    page_size = 100
    cur_page = 0
    total_records = -1
    full_result = "["
    while not b_download_finished:
        url_download_log = (f"https://codecheck-ext.cn-north-4.myhuaweicloud.com/"
                            f"v2/tasks/{job_id}/defects-detail?limit={page_size}&offset={cur_page}&severity=0")
        res = requests.get(url=url_download_log, headers=common_header, verify=False)
        full_result += res.text + ','
        cur_page += 1
        total_records = total_records if total_records != -1 else int(json.loads(res.text)['total'])
        b_download_finished = cur_page * page_size >= total_records
        logging.info(f"    > get code check log: total {total_records} records, got {cur_page * page_size}")
    return full_result[:-1] + ']', store_path


def add_status_info_to_comment(job, log_path, artifact_path, b_download_error):
    global comment_body
    log_href_url = 'no log available' if b_download_error else\
        ("<a href='" + f"https://ascend-cann-open.obs.cn-north-4.myhuaweicloud.com/demo/build-logs/{pipeline_run_id}/{log_path}" +
         "'>download</a>")
    artifact_href_url = "" if artifact_path is None else\
        ("<a href='" + f"https://ascend-cann-open.obs.cn-north-4.myhuaweicloud.com/demo/build-artifacts/{pipeline_run_id}/{artifact_path}" +
         "'>download</a>")
    job_status = "EXCEPTION" if b_download_error else job['status']
    comment_body += (f"<tr>"
                     f"<td>{job['name']}</td>"
                     f"<td>{job_status}</td>"
                     f"<td>{log_href_url}</td>"  # 这里注意，跟构建配制要保持一致，以及log文件名跟下载环节保持一致
                     f"<td>{artifact_href_url}</td>"  # 这里注意，跟构建配制要保持一致，以及log文件名跟下载环节保持一致
                     f"</tr>")


def post_comment_to_repo():
    logging.info("上报流水线执行结果：\n" + comment_body)
    url_post_repo_comment = f'https://gitee.com/api/v5/repos/{repo_path}/pulls/{pr_id}/comments'
    post_data = {
        "access_token": repo_access_token,
        "body": comment_header + comment_body + comment_tail
    }
    response = requests.post(url_post_repo_comment, data=post_data, verify=False)
    if response.status_code in [200, 201, 204]:
        logging.info(f'comment success')
    else:
        logging.info(f'comment failed')
        logging.info(response.text)


def main_process():
    b_pipeline_is_running = True
    track_stages = ["二进制检查", "UT测试", "编译", "代码检查"]
    jobs_completed = []
    while b_pipeline_is_running:
        time.sleep(60)
        current_status = get_pipeline_status()
        b_pipeline_is_running = current_status['status'] == "RUNNING"
        logging.info(f"流水线当前运行状态：{current_status['status']}")
        stages = current_status["stages"]
        for stage in stages:
            logging.info(f"> stage[{stage['name']}]当前状态：{stage['status']}")
            if stage["status"] == "INIT":  # 未执行阶段直接退出，基于PR触发不会跳过中间阶段为前提，手动执行不适用
                break
            if not stage["name"] in track_stages:
                continue
            for job in stage["jobs"]:
                logging.info(f"  > job[{job['name']}]当前状态：{job['status']}")
                if job["status"] == "RUNNING" or job["status"] == "INIT" or job['identifier'] in jobs_completed:
                    continue
                artifact_path = None if job['status'] != "COMPLETED" or job['name'] not in job_path_dict else\
                    job_path_dict[job['name']]

                try:
                    log_path = download_job_log(job)
                    log_path = "/".join(log_path.split(os.path.sep)[1:])
                    add_status_info_to_comment(job, log_path, artifact_path, False)
                except:
                    logging.error(f"下载日志失败 >>> job[{job['name']}]")
                    add_status_info_to_comment(job, "", artifact_path, True)
                jobs_completed.append(job['identifier'])


if __name__ == '__main__':
    # 动态设置全局变量

    logging.info("project_id: " + project_id)
    logging.info("pipeline_id: " + pipeline_id)
    logging.info("pipeline_run_id: " + pipeline_run_id)
    logging.info("build_number: " + build_number)
    logging.info("repo_path: " + repo_path)
    logging.info("pr_id:" + pr_id)
    logging.info("iamPassword: " + hw_cloud_iam_password[:3] + '*' * 5 + hw_cloud_iam_password[-3:])
    logging.info("repo_access_token: " + repo_access_token[:3] + '*' * 5 + repo_access_token[-3:])

    get_token()
    common_header = {"x-auth-token": token}

    main_process()
    # 这里默认文件会上传成功（流水线中的上传OBS插件完成），待优化
    post_comment_to_repo()
    # TODO：为了调试，记得删除
    exit(1)
